﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using NUnit.Framework.Constraints;
using NUnit.Framework;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;

using SAKS.Models;

namespace SAKS.UnitTest.ModelsTest
{
    [TestFixture]
    public class UserModelTest : TestBase
    {
        protected override void CreateSomeData(ISession session)
        {
            var user = new User()
            {
                UserName = "NoDeleting",
                LoweredUserName = "nodeleting",
                IsAnonymous = false,
                LastActivityDate = DateTime.Now
            };
            var from = new User()
            {
                UserName = "From",
                LoweredUserName = "From",
                IsAnonymous = false,
                LastActivityDate = DateTime.Now
            };
            var to = new User()
            {
                UserName = "To",
                LoweredUserName = "to",
                IsAnonymous = false,
                LastActivityDate = DateTime.Now
            };
            var role = new Role()
            {
                RoleName = "NoDeleting",
                Users = new List<User>()
            };
            var project = new Project()
            {
                Name = "NoDeleting"
            };

            session.Save(to);
            session.Save(from);
            session.Save(project);
            session.Save(user);
            session.Save(role);
            session.Flush();
        }

        #region role
        [Test]
        public void AddRoleToUserTest()
        {
            User user = new User()
            {
                UserName = "kingzs70",
                LoweredUserName = "kingzs70",
                IsAnonymous = false,
                LastActivityDate = DateTime.Now,
                Roles = new List<Role>()
            };
            var membership = new Membership
            {
                Password = "123456",
                PasswordFormat = 0,
                Email = "AddMembershipToUserTest@126.com",
                LoweredEmail = "AddMembershipToUserTest@126.com",
                CreateDate = DateTime.Now,
                LastLoginDate = DateTime.Now,
                LastPasswordChangedDate = DateTime.Now,
            };
            var role = new Role()
            {
                RoleName = "Admin",
                Users = new List<User>()
            };

            using (var session = sessionFactory.OpenSession())
            {

                using (var tx = session.BeginTransaction())
                {
                    //Add
                    session.Save(user);
                    session.Save(role);
                    user.Roles.Add(role);
                    user.Membership = membership;
                    membership.User = user;
                    session.Update(user);//这里无论是更新user还是更新role，都更新SAKS_User和SAKS_Role表，并插入User_In_Role
                    tx.Commit();
                    session.Refresh(role);
                    Assert.IsTrue(role.Users.Count > 0);

                    session.Delete(user);
                    session.Delete(role);
                }
            }
        }
        [Test]
        public void RemoveRoleFromUserTest()
        {
            User user = new User()
            {
                UserName = "RemoveRoleFromUserTest",
                LoweredUserName = "RemoveRoleFromUserTest",
                IsAnonymous = false,
                LastActivityDate = DateTime.Now,
                Roles = new List<Role>()
            };
            var role = new Role()
            {
                RoleName = "RemoveRoleFromUserTest",
                Users = new List<User>()
            };

            using (var session = sessionFactory.OpenSession())
            {

                using (var tx = session.BeginTransaction())
                {
                    //Add
                    session.Save(user);
                    session.Save(role);
                    user.Roles.Add(role);
                    session.Update(user);//这里无论是更新user还是更新role，都更新SAKS_User和SAKS_Role表，并插入User_In_Role
                    session.Flush();
                    session.Refresh(role);

                    Assert.IsFalse(role.Users.Count == 0);
                    user.Roles.Remove(role);
                    session.Update(user);
                    tx.Commit();
                    session.Refresh(role);

                    Assert.IsTrue(role.Users.Count == 0);
                }
            }
        }
        [Test]
        public void DeleteUserCheckOnRoleTest()
        {
            var role = new Role()
            {
                RoleName = "DeleteUserTest",
                Users = new List<User>()
            };
            User user = new User()
            {
                UserName = "DeleteUserTest",
                LoweredUserName = "DeleteUserTest",
                IsAnonymous = false,
                LastActivityDate = DateTime.Now,
                Roles = new List<Role>()
            };

            //删除用户，同时删除和角色的关系，但不能级联删除角色
            using (var session = sessionFactory.OpenSession())
            {
                session.Save(user);
                session.Save(role);
                user.Roles.Add(role);
                session.Update(user);//invers= true 属性标在了role端，说明role端只是个镜像，role和user的关系由user端维护，所以需要更新user，而不是role
                session.Flush();

                session.Refresh(role);
                Assert.IsFalse(role.Users.Count == 0);//删除role之前 role中有一个user
                session.Delete(user);
                session.Flush();
                session.Refresh(role);
                Assert.IsTrue(role.Users.Count == 0);//删除role之后 role中有0个user

                session.Delete(user);
                session.Delete(role);
            }
        }
        [Test]
        public void DeleteRoleFailedTest()
        {
            var role = new Role()
            {
                RoleName = "DeleteRoleTest",
                Users = new List<User>()
            };
            User user = new User()
            {
                UserName = "DeleteRoleTest",
                LoweredUserName = "DeleteRoleTest",
                IsAnonymous = false,
                LastActivityDate = DateTime.Now,
                Roles = new List<Role>()
            };

            //删除角色，同时删除和用户的关系，但不能级联删除用户
            using (var session = sessionFactory.OpenSession())
            {
                session.Save(user);
                session.Save(role);
                user.Roles.Add(role);
                session.Update(user);
                session.Flush();
                //由于user端的cascade为“save-update",所以删除不了role
                try
                {
                    session.Delete(role);
                    session.Flush();
                    session.Refresh(user);
                    Assert.IsFalse(true);
                }
                catch (Exception)
                {
                    Assert.IsTrue(true);
                    session.Delete(user);
                    session.Delete(role);
                }


            }

        }
        #endregion

        #region membership
        [Test]
        public void AddMembershipToUserTest()
        {
            var membership = new Membership()
            {
                Password = "12345",
                PasswordFormat = 0,
                Email = "AddMembershipToUserTest@126.com",
                LoweredEmail = "AddMembershipToUserTest@126.com",
                CreateDate = DateTime.Now,
                LastLoginDate = DateTime.Now,
                LastPasswordChangedDate = DateTime.Now,
            };
            using (var session = sessionFactory.OpenSession())
            {
                var user = session.QueryOver<User>().Where(u => u.UserName == "NoDeleting").SingleOrDefault();
                Assert.NotNull(user);

                membership.User = user;
                session.Save(membership);
                session.Flush();
                session.Refresh(user);

                Assert.IsTrue(user.Membership.User.Id == user.Id);
            }
        }
        [Test]
        public void CreateUserWithMembershipTest()
        {
            var membership = new Membership()
            {
                Password = "12345",
                PasswordFormat = 0,
                Email = "CreateUserWithMembershipTest@126.com",
                LoweredEmail = "CreateUserWithMembershipTest@126.com",
                CreateDate = DateTime.Now,
                LastLoginDate = DateTime.Now,
                LastPasswordChangedDate = DateTime.Now,
            };
            var user = new User()
            {
                UserName = "CreateUserWithMembershipTest",
                LoweredUserName = "CreateUserWithMembershipTest",
                IsAnonymous = false,
                LastActivityDate = DateTime.Now,
                Membership = membership
            };
            membership.User = user;

            using (var session = sessionFactory.OpenSession())
            {
                session.Save(user);
                session.Flush();

                var fetchout = session.QueryOver<User>().Where(u => u.UserName == "CreateUserWithMembershipTest").SingleOrDefault().Membership;
                Assert.AreEqual(fetchout.Password ,"12345");
            }

            
        }
        [Test]
        public void DeleteUserCheckOnMembershipTest()
        {
            var membership = new Membership()
            {
                Password = "12345",
                PasswordFormat = 0,
                Email = "DeleteUserCheckOnMembershipTestkingzsnew@126.com",
                LoweredEmail = "DeleteUserCheckOnMembershipTestkingzsnew@126.com",
                CreateDate = DateTime.Now,
                LastLoginDate = DateTime.Now,
                LastPasswordChangedDate = DateTime.Now,
            };
            User user = new User()
            {
                UserName = "DeleteUserCheckOnMembershipTest",
                LoweredUserName = "DeleteUserCheckOnMembershipTest",
                IsAnonymous = false,
                LastActivityDate = DateTime.Now,
            };
            using (var session = sessionFactory.OpenSession())
            {
                user.Membership = membership;
                membership.User = user;//必须双向指定关系
                session.Save(user);
                session.Flush();

                session.Delete(user);
                session.Flush();

                Assert.IsTrue(session.QueryOver<Membership>().Where(m => m.Email == "DeleteUserCheckOnMembershipTestkingzsnew@126.com").SingleOrDefault() == null);
            }
        }
        #endregion



        #region project

        [Test]
        public void AddAndRemoveProjectToUserTest()
        {
            var project = new Project()
            {
                Name = "AddAndRemoveProjectToUserTest",
                Users = new List<User>()
            };
            var user = new User()
            {
                UserName = "AddAndRemoveProjectToUserTest",
                LoweredUserName = "AddAndRemoveProjectToUserTest",
                IsAnonymous = false,
                LastActivityDate = DateTime.Now,
                Projects = new List<Project>()
            };

            using (var session = sessionFactory.OpenSession())
            {

                user.Projects.Add(project);
                session.Save(user);
                session.Flush();

                session.Refresh(project);
                Assert.IsFalse(project.Users.Count == 0);
                user.Projects.Remove(project);
                session.Update(user);
                session.Flush();
                session.Refresh(project);
                Assert.IsTrue(project.Users.Count == 0);
            }
        }
        #endregion


    }
}
